package com.wuliang.generate.common.core.utils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.wuliang.generate.common.core.response.ReturnCode;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.context.annotation.Lazy;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * JWT 令牌工具
 * @author WuLiang
 */
@Lazy
public class JwtTokenUtils {

    public static final String TOKEN_HEADER = "Token";
    public static final String TOKEN_PREFIX = "Bearer";

    private static final String SECRET = "jwtsecretdemo";
    private static final String ISS = "echisan";

    /**
     * 过期时间
     */
    private static final long EXPIRATION = 43200L;

    /**
     * 选择了记住我之后的过期时间为7天
     */
    private static final long EXPIRATION_REMEMBER = 604800L;

    /**
     * 创建token
     */
    public static String createToken(String username, boolean isRememberMe) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setIssuer(ISS)
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(
                        (System.currentTimeMillis() + (!isRememberMe ? EXPIRATION : EXPIRATION_REMEMBER) * 1000)))
                .compact();
    }

    public static String createToken(String content, long expirationTime) {
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setIssuer(ISS)
                .setIssuedAt(new Date())
                .setSubject(content)
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                .compact();
    }

    /**
     * 是否已过期
     */
    public static boolean isExpiration(String token) {
        return getTokenBody(token).getExpiration().before(new Date());
    }

    public static Claims getTokenBody(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从token中获取用户名
     *
     * @return
     */
    public static Map<String, Object> getAuthenticationDetail(HttpServletRequest request) {
        return getAuthenticationDetail(request.getHeader(TOKEN_HEADER));
    }

    public static Map<String, Object> getAuthenticationDetail(String token) {
        if (token.contains(TOKEN_PREFIX)) {
            token = token.replace(TOKEN_PREFIX, "").trim();
        }
        if (isExpiration(token)) {
            throw new RuntimeException(ReturnCode.CREDENTIALS_EXPIRED.getMessage());
        }
        if (token.isEmpty()) {
            throw new RuntimeException("凭据错误，请重新登录！");
        }
        String json = getTokenBody(token).getSubject();
        if (JsonUtils.isObject(json)) {
            return new Gson().fromJson(json, new TypeToken<Map<String, Object>>() {
            }.getType());
        }
        return new LinkedHashMap<>();
    }

    public static Integer getUserIdFromToken(String token) {
        Map<String, Object> authenticationDetail = getAuthenticationDetail(token);
        return authenticationDetail.get("ID") == null ? null : ((Number) authenticationDetail.get("ID")).intValue();
    }

    public static Integer getUserIdFromToken(HttpServletRequest request) {
        return getUserIdFromToken(request.getHeader(TOKEN_HEADER));
    }

}
